package com.axdac.mixbind.view;

import android.app.Activity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;


import com.axdac.mixbind.TimeLine;

import java.lang.reflect.Field;
import java.util.HashMap;

/**
 * Created by Administrator on 2018/5/19 0019.
 * note: decalara means a  class which use @Bind to
 * mark the Object for binding view Object
 */

public class MixBind {
    private View root;
    private Activity activity;
    private Object decalare;
    public final static int BEFORE_INIT = -9999;
    public final static int AFIER_INIT = 9999;
    protected HashMap<String,Object> data;
    TimeLine.Builder builder;

    /**
     * this init stage is when you want to by a view
     * with data builder object,not in a activity
     *  MixBind mixBind = new MixBind(view,databuilder);
     *  mixBind.startbind();
     */
    public MixBind(View root, Object decalare) {
        this.root = root;
        this.decalare = decalare;
        data =new HashMap<>();
        builder = new TimeLine.Builder();
    }

    /**
     * this init stage is when you want to by a view
     * in activity
     *  MixBind mixBind = new MixBind(this);
     *  mixBind.startbind();
     */
    public MixBind(Activity activity) {
        this.activity = activity;
        data =new HashMap<>();
        builder = new TimeLine.Builder();
    }

    /**
     * when you want to do other job when you binding view ,
     * inject a lib into binder
     * @param object
     */
    public void injectLib(Object object){
        builder.addlib(object);
    }

    /**
     * start bind
     * if activity is not null ,use it datamaker
     * or user should supply a datamaker
     */
    public void startbind()  {
        builder.addlib(this);
        try {
            Object del = activity!=null?activity:decalare;
            Class<?> clazz = del.getClass();
            if (clazz.isAnnotationPresent(MixCombat.class)) {
                MixCombat combat = clazz.getAnnotation(MixCombat.class);
                String DataMakerClazz = combat.dataMakers();
                Class pre = Class.forName(DataMakerClazz);
                builder.addlib(pre.newInstance());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        builder.run();
    }

    @TimeLine.TimeLineTick(level = BEFORE_INIT,thread = TimeLine.TimeLineTick.FORGROUND)
    public void beforeInit(TimeLine.RunningMsg msg){
        if (activity!=null) {
            msg.map.put("Intent", activity.getIntent());
            msg.map.put("Context", activity.getApplicationContext());
        }else{
            msg.map.put("Context",root.getContext().getApplicationContext());
        }

    }

    @TimeLine.TimeLineTick(level = AFIER_INIT,thread = TimeLine.TimeLineTick.FORGROUND)
    public void afterInit(TimeLine.RunningMsg msg){
        try {
            msg.map.remove("Context");
            msg.map.remove("Intent");
        }catch (Exception e){
            e.printStackTrace();
        }

        data.putAll(msg.map);

        try {
            if (activity==null){
                bindByObject();
            }else{
                bindByActivity();
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    private void bindByActivity() throws IllegalAccessException, ClassNotFoundException, InstantiationException {
        Class<?> clazz = activity.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields){
            field.setAccessible(true);
            Bind mixBind = field.getAnnotation(Bind.class);
            if(mixBind!=null){
                int fieldViewID = mixBind.viewId();
                String HandlerClass = mixBind.handler();
                String valueKey = mixBind.valueKey();
                View view = activity.findViewById(fieldViewID);
                field.set(activity,view);
                if(!valueKey.equals("")){
                    bind(view,valueKey,HandlerClass,data);
                }
            }
        }
    }

    public static void bind(View view,String valueKey,String HandlerClass,HashMap<String,Object> data) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        IBindView bindView = null;
        if(HandlerClass.equals(Bind.Default)){
            if (view instanceof TextView){
                bindView = new MixTextViewBinder();
            }else if (view instanceof EditText){
                bindView = new MixEditTextBinder();
            }else if (view instanceof Button){
                bindView = new MixButtonBinder();
            }else if (view instanceof Button){
                bindView = new MixButtonBinder();
            }else if(view instanceof ListView){
                bindView = new MixListViewBinder();
            }else {
                bindView = new MixDefaultBinder();
            }
        }else{
            bindView = (IBindView) Class.forName(HandlerClass).newInstance();
        }
        bindView.onBind(view,data.get(valueKey));
    }

    private void bindByObject() throws IllegalAccessException, ClassNotFoundException, InstantiationException {
        Class<?> clazz = decalare.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields){
            field.setAccessible(true);
            Bind mixBind = field.getAnnotation(Bind.class);
            if(mixBind!=null){
                int fieldViewID = mixBind.viewId();
                String HandlerClass = mixBind.handler();
                String valueKey = mixBind.valueKey();
                View view = root.findViewById(fieldViewID);
                field.set(decalare,view);
                if(!valueKey.equals("")){
                    bind(view,valueKey,HandlerClass,data);
                }
            }
        }
    }

    //----------------------------------------------------------------------------------------------------------------------------
    public static void OnlyBindView(View root,Object decalare) throws IllegalAccessException {
        Class<?> clazz = decalare.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields){
            field.setAccessible(true);
            Bind mixBind = field.getAnnotation(Bind.class);
            if(mixBind!=null){
                int fieldViewID = mixBind.viewId();
                View view = root.findViewById(fieldViewID);
                field.set(decalare,view);
            }
        }
    }
    public static void BindViewWithData(View root,Object decalare,HashMap<String,Object> map) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        Class<?> clazz = decalare.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields){
            field.setAccessible(true);
            Bind mixBind = field.getAnnotation(Bind.class);
            if(mixBind!=null){
                int fieldViewID = mixBind.viewId();
                String HandlerClass = mixBind.handler();
                String valueKey = mixBind.valueKey();
                View view = root.findViewById(fieldViewID);
                field.set(decalare,view);
                if(!valueKey.equals("")){
                    bind(view,valueKey,HandlerClass,map);
                }
            }
        }
    }

    public static void OnlyBindView(Activity activity) throws IllegalAccessException {
        Class<?> clazz = activity.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields){
            field.setAccessible(true);
            Bind mixBind = field.getAnnotation(Bind.class);
            if(mixBind!=null){
                int fieldViewID = mixBind.viewId();
                View view = activity.findViewById(fieldViewID);
                field.set(activity,view);
            }
        }
    }
    public static void BindViewWithData(Activity activity,HashMap<String,Object> map) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        Class<?> clazz = activity.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields){
            field.setAccessible(true);
            Bind mixBind = field.getAnnotation(Bind.class);
            if(mixBind!=null){
                int fieldViewID = mixBind.viewId();
                String HandlerClass = mixBind.handler();
                String valueKey = mixBind.valueKey();
                View view = activity.findViewById(fieldViewID);
                field.set(activity,view);
                if(!valueKey.equals("")){
                    bind(view,valueKey,HandlerClass,map);
                }
            }
        }
    }

    public void clear(){
        activity=null;
        decalare=null;
        root=null;
    }


}
